﻿/* 
* Copyright (c) 2010, The University of Texas at Austin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation and/or other materials 
* provided with the distribution.
*
* Neither the name of The University of Texas at Austin nor the names of its contributors may be 
* used to endorse or promote products derived from this software without specific prior written 
* permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Windows.Input;
using System.Windows.Media;
using Bio.Views.Structure.Editor.Internal.Rendering.Interfaces;
using Bio.Views.Structure.Editor.ViewModels;
using Bio.Views.Structure.Editor.Views;
using JulMar.Windows.Interfaces;
using JulMar.Windows.Mvvm;

namespace Bio.Views.Structure.Editor.Internal.Commands
{
    public class StructureEditorCommands
    {
        private static ColorConverter COLOR_CONVERTER;

        static StructureEditorCommands()
        {
            COLOR_CONVERTER = new ColorConverter();
            ChangeNucleotideFill = new RoutedCommand();
            ChangeNucleotideCircleFill = new RoutedCommand();
            ChangeNucleotideCircleStroke = new RoutedCommand();
            ChangeBasePairConnectorFill = new RoutedCommand();
            ChangeBasePairConnectorStroke = new RoutedCommand();
        }

        public static readonly RoutedCommand ChangeNucleotideFill;
        public static readonly RoutedCommand ChangeNucleotideCircleFill;
        public static readonly RoutedCommand ChangeNucleotideCircleStroke;
        public static readonly RoutedCommand ChangeBasePairConnectorFill;
        public static readonly RoutedCommand ChangeBasePairConnectorStroke;
        public static readonly RoutedCommand SaveChanges;
        public static readonly RoutedCommand UndoLastChange;
        public static readonly RoutedCommand UndoAll;

        public static void OnCanEditVisualComponentBrush(object sender, CanExecuteRoutedEventArgs args)
        {
            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                args.CanExecute = true;
                return;
            }
            args.CanExecute = false;
        }

        public static void OnChangeBasePairConnectorStroke(object sender, ExecutedRoutedEventArgs args)
        {
            if (args.Parameter == null)
                throw new ArgumentException(string.Format("Error: Expected an IStructureElementVisualComponent parameter"));

            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                try
                {
                    StructureElementBrushEditorViewModel vm = null;
                    bool? hasInheritanceState = null;
                    try
                    {
                        hasInheritanceState = component.IsBasePairConnectorStrokeInheriting(); //For example a range component dosen't support this call since its a proxy for a set of visuals, so we have to have a fallback.
                    }
                    catch (NotSupportedException) { hasInheritanceState = null; }

                    if (hasInheritanceState.HasValue)
                    {
                        vm = (hasInheritanceState.Value) ? new StructureElementBrushEditorViewModel() : new StructureElementBrushEditorViewModel(component.BasePairConnectorStroke.ToString());
                    }
                    else
                    {
                        vm = (component.BasePairConnectorStroke == null) ? new StructureElementBrushEditorViewModel(null) : new StructureElementBrushEditorViewModel(component.BasePairConnectorStroke.ToString());
                    }

                    IUIVisualizer uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();
                    if (uiVisualizer != null)
                    {
                        bool? result = uiVisualizer.ShowDialog(typeof(StructureElementBrushEditor).ToString(), vm);
                        if (result != null && result.Value)
                        {
                            if (vm.ShouldInherit)
                            {
                                component.BasePairConnectorStroke = null;
                            }
                            else
                            {
                                Color requestedColor = (Color)COLOR_CONVERTER.ConvertFrom(vm.Color);
                                component.BasePairConnectorStroke = new SolidColorBrush(requestedColor);
                            }
                        }
                    }
                }
                catch (NotSupportedException)
                {
                    IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                    errMesg.Show("Error",
                        string.Format("Error: Selected Structure Element does not support Base Pair Connector Properties"));
                }
                catch (Exception e)
                {
                    IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                    errMesg.Show("Error",
                        string.Format("Error: \n{0}\n{1}", e.Message, e.StackTrace));
                }
            }
        } 

        public static void OnChangeBasePairConnectorFill(object sender, ExecutedRoutedEventArgs args)
        {
            if (args.Parameter == null)
                throw new ArgumentException(string.Format("Error: Expected an IStructureElementVisualComponent parameter"));

            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                try
                {
                    StructureElementBrushEditorViewModel vm = null;
                    bool? hasInheritanceState = null;
                    try
                    {
                        hasInheritanceState = component.IsBasePairConnectorFillInheriting(); //For example a range component dosen't support this call since its a proxy for a set of visuals, so we have to have a fallback.
                    }
                    catch (NotSupportedException) { hasInheritanceState = null; }

                    if (hasInheritanceState.HasValue)
                    {
                        vm = (hasInheritanceState.Value) ? new StructureElementBrushEditorViewModel() : new StructureElementBrushEditorViewModel(component.BasePairConnectorFill.ToString());
                    }
                    else
                    {
                        vm = (component.BasePairConnectorFill == null) ? new StructureElementBrushEditorViewModel(null) : new StructureElementBrushEditorViewModel(component.BasePairConnectorFill.ToString());
                    }

                    IUIVisualizer uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();
                    if (uiVisualizer != null)
                    {
                        bool? result = uiVisualizer.ShowDialog(typeof(StructureElementBrushEditor).ToString(), vm);
                        if (result != null && result.Value)
                        {
                            if (vm.ShouldInherit)
                            {
                                component.BasePairConnectorFill = null;
                            }
                            else
                            {
                                Color requestedColor = (Color)COLOR_CONVERTER.ConvertFrom(vm.Color);
                                component.BasePairConnectorFill = new SolidColorBrush(requestedColor);
                            }
                        }
                    }
                }
                catch (NotSupportedException)
                {
                    IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                    errMesg.Show("Error",
                        string.Format("Error: Selected Structure Element does not support Base Pair Connector Properties"));
                }
                catch (Exception e)
                {
                    IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                    errMesg.Show("Error",
                        string.Format("Error: \n{0}\n{1}", e.Message, e.StackTrace));
                }
            }
        }

        public static void OnChangeNucleotideCircleStroke(object sender, ExecutedRoutedEventArgs args)
        {
            if (args.Parameter == null)
                throw new ArgumentException(string.Format("Error: Expected an IStructureElementVisualComponent parameter"));

            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                StructureElementBrushEditorViewModel vm = null;
                bool? hasInheritanceState = null;
                try
                {
                    hasInheritanceState = component.IsNucleotideCircleStrokeInheriting(); //For example a range component dosen't support this call since its a proxy for a set of visuals, so we have to have a fallback.
                }
                catch (NotSupportedException) { hasInheritanceState = null; }

                if (hasInheritanceState.HasValue)
                {
                    vm = (hasInheritanceState.Value) ? new StructureElementBrushEditorViewModel() : new StructureElementBrushEditorViewModel(component.NucleotideCircleStroke.ToString());
                }
                else
                {
                    vm = (component.NucleotideCircleStroke == null) ? new StructureElementBrushEditorViewModel(null) : new StructureElementBrushEditorViewModel(component.NucleotideCircleStroke.ToString());
                }

                IUIVisualizer uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();
                if (uiVisualizer != null)
                {
                    bool? result = uiVisualizer.ShowDialog(typeof(StructureElementBrushEditor).ToString(), vm);
                    if (result != null && result.Value)
                    {
                        if (vm.ShouldInherit)
                        {
                            component.NucleotideCircleStroke = null;
                        }
                        else
                        {
                            try
                            {
                                Color requestedColor = (Color)COLOR_CONVERTER.ConvertFrom(vm.Color);
                                component.NucleotideCircleStroke = new SolidColorBrush(requestedColor);
                            }
                            catch (Exception e)
                            {
                                IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                                errMesg.Show("Error",
                                    string.Format("Error: \n{0}\n{1}", e.Message, e.StackTrace));
                            }
                        }
                    }
                }
            }
        }

        public static void OnChangeNucleotideCircleFill(object sender, ExecutedRoutedEventArgs args)
        {
            if (args.Parameter == null)
                throw new ArgumentException(string.Format("Error: Expected an IStructureElementVisualComponent parameter"));

            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                StructureElementBrushEditorViewModel vm = null;
                bool? hasInheritanceState = null;
                try
                {
                    hasInheritanceState = component.IsNucleotideCircleFillInheriting(); //For example a range component dosen't support this call since its a proxy for a set of visuals, so we have to have a fallback.
                }
                catch (NotSupportedException) { hasInheritanceState = null; }

                if (hasInheritanceState.HasValue)
                {
                    vm = (hasInheritanceState.Value) ? new StructureElementBrushEditorViewModel() : new StructureElementBrushEditorViewModel(component.NucleotideCircleFill.ToString());
                }
                else
                {
                    vm = (component.NucleotideCircleFill == null) ? new StructureElementBrushEditorViewModel(null) : new StructureElementBrushEditorViewModel(component.NucleotideCircleFill.ToString());
                }

                IUIVisualizer uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();
                if (uiVisualizer != null)
                {
                    bool? result = uiVisualizer.ShowDialog(typeof(StructureElementBrushEditor).ToString(), vm);
                    if (result != null && result.Value)
                    {
                        if (vm.ShouldInherit)
                        {
                            component.NucleotideCircleFill = null;
                        }
                        else
                        {
                            try
                            {
                                Color requestedColor = (Color)COLOR_CONVERTER.ConvertFrom(vm.Color);
                                component.NucleotideCircleFill = new SolidColorBrush(requestedColor);
                            }
                            catch (Exception e)
                            {
                                IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                                errMesg.Show("Error",
                                    string.Format("Error: \n{0}\n{1}", e.Message, e.StackTrace));
                            }
                        }
                    }
                }
            }
        }

        public static void OnChangeNucleotideFill(object sender, ExecutedRoutedEventArgs args)
        {
            if (args.Parameter == null)
                throw new ArgumentException(string.Format("Error: Expected an IStructureElementVisualComponent parameter"));

            IStructureElementVisualComponent component = args.Parameter as IStructureElementVisualComponent;
            if (component != null)
            {
                StructureElementBrushEditorViewModel vm = null;
                bool? hasInheritanceState = null;
                try
                {
                    hasInheritanceState = component.IsNucleotideFillInheriting(); //For example a range component dosen't support this call since its a proxy for a set of visuals, so we have to have a fallback.
                }
                catch (NotSupportedException) { hasInheritanceState = null; }

                if (hasInheritanceState.HasValue)
                {
                    vm = (hasInheritanceState.Value) ? new StructureElementBrushEditorViewModel() : new StructureElementBrushEditorViewModel(component.NucleotideFill.ToString());
                }
                else
                {
                    vm = (component.NucleotideFill == null) ? new StructureElementBrushEditorViewModel(null) : new StructureElementBrushEditorViewModel(component.NucleotideFill.ToString());
                }

                IUIVisualizer uiVisualizer = ViewModel.ServiceProvider.Resolve<IUIVisualizer>();
                if (uiVisualizer != null)
                {
                    bool? result = uiVisualizer.ShowDialog(typeof(StructureElementBrushEditor).ToString(), vm);
                    if (result != null && result.Value)
                    {
                        if (vm.ShouldInherit)
                        {
                            component.NucleotideFill = null;
                        }
                        else
                        {
                            try
                            {
                                Color requestedColor = (Color)COLOR_CONVERTER.ConvertFrom(vm.Color);
                                component.NucleotideFill = new SolidColorBrush(requestedColor);
                            }
                            catch (Exception e)
                            {
                                IErrorVisualizer errMesg = ViewModel.ServiceProvider.Resolve<IErrorVisualizer>();
                                errMesg.Show("Error",
                                    string.Format("Error: \n{0}\n{1}", e.Message, e.StackTrace));
                            }
                        }
                    }
                }
            }
        }       
    }
}
